package actions;

import java.io.File;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.action.DynaActionForm;
import org.apache.struts.upload.FormFile;

import service.UploadedFileService;
import utils.HuaXiaFileUtils;
import domain.RelatedFile;
import exceptions.AppException;

/**
 * 多文件上传.
 * @author liwp.
 */
public class CommonFileUploadAction extends Action {

    /**
     * 文件上传放置的根目录. 如果这个值为'//'开始的字符串，表明这个路径是一个操作系统规定的绝对路径，比如//D:/data/images
     * 或者///local/home/images，否则，表明这是一个web下的相对路径,比如/data/images .*
     */
    private String fileRootPath;

    /** UploadedFileService ** */
    private UploadedFileService uploadedFileService;

    /**
     * @param mapping action mapping
     * @param form action form
     * @param request http request
     * @param response http response
     * @return action forward
     * @throws Exception any exception
     */
    public ActionForward execute(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        DynaActionForm uploadForm = (DynaActionForm) form;
        String topic = uploadForm.getString("topic");
        if (topic == null || topic.equals("")) {
            topic = request.getParameter("topic");
            if (topic == null || topic.equals("")) {
                throw new AppException("must provide request param topic");
            } else {
                uploadForm.set("topic", topic);
            }
        }
        String relatedTo = uploadForm.getString("relatedTo");
        if (relatedTo == null || relatedTo.equals("")) {
            relatedTo = request.getParameter("relatedTo");
            if (relatedTo == null || relatedTo.equals("")) {
                throw new AppException("must provide request param relatedTo");
            } else {
                uploadForm.set("relatedTo", relatedTo);
            }
        }
        String action = (String) request.getParameter("action");
        // 根据action 分发动作
        if ("上传".equals(action)) {
            return uploadFile(mapping, uploadForm, request, topic, relatedTo);

        } else if ("删除".equals(action)) {
            String delFileId = (String) request.getParameter("selectFileId");
            return deleteUploadedFile(mapping, Integer.parseInt(delFileId));
        } else {
            return mapping.findForward("upload");
        }
    }

    /**
     * 删除选中的已上传的文件.
     * @param mapping mapping.
     * @param delFileId 删除文件.
     * @return forward.
     */
    private ActionForward deleteUploadedFile(ActionMapping mapping,
            int delFileId) {
        uploadedFileService.removeUploadedFileInfo(Integer.valueOf(delFileId),
                true);
        return mapping.findForward("upload");
    }

    /**
     * 上传文件逻辑.
     * @param mapping mapping
     * @param uploadForm dynform
     * @param request request
     * @param topic 相关联对象的分类
     * @param relatedTo 相关连的对象id
     * @return forward
     */
    private ActionForward uploadFile(ActionMapping mapping,
            DynaActionForm uploadForm, HttpServletRequest request,
            String topic, String relatedTo) {

        FormFile formfile = (FormFile) uploadForm.get("uploadFile");
        String fileName = formfile.getFileName();

        // 检查是否有文件上传
        if (fileName == null || fileName.equals("")) {
            ActionMessages errMsgs = new ActionMessages();
            errMsgs.add("uploadFile", new ActionMessage(
                    "errors.uploadFile.fileName.isEmpty"));
            // 保存错误信息并重定向到输入界面
            this.saveErrors(request, errMsgs);
            return mapping.findForward("upload");
        }
        // 构建上传文件信息.
        RelatedFile fileInfo = buildFileFullName(topic, relatedTo, fileName);
        fileInfo.setSize(formfile.getFileSize());
        // 是否强制覆盖已有的文件.
        boolean forceUpload = "true"
                .equals(uploadForm.getString("forceUpload"));
        // 恢复forceUpload 为“非选状态”，防止用户不小心覆盖了服务器上已经存在的文件.
        uploadForm.set("forceUpload", null);
        if (!forceUpload && new File(fileInfo.getFullName()).exists()) {
            // 检查是否有重复文件在服务器上存在.
            ActionMessages errMsgs = new ActionMessages();
            errMsgs.add("uploadFile", new ActionMessage(
                    "errors.uploadFile.already.exist"));
            // 保存错误信息并重定向到输入界面
            this.saveErrors(request, errMsgs);
            return mapping.findForward("upload");
        }

        // 上传文件
        HuaXiaFileUtils.saveUploadFile(formfile, fileInfo.getFullName());
        uploadedFileService.addUploadedFileInfo(fileInfo);
        return mapping.findForward("upload");
    }

    /**
     * 根据上传的文件名 以及关联的对象id,构建子目录及完整文件名.
     * @param topic 主体（也可以说相关联对象的一种分类).
     * @param fileName filename
     * @param relatedTo 相关联的对象id
     * @return RelatedFile fileInfo
     */
    private RelatedFile buildFileFullName(String topic, String relatedTo,
            String fileName) {
        String theFileRootPath = HuaXiaFileUtils.getRealFileName(servlet
                .getServletContext(), this.fileRootPath);
        File path = new File(theFileRootPath, topic);
        path = new File(path, relatedTo);
        if (!path.exists()) {
            path.mkdirs();
        }
        RelatedFile fileInfo = new RelatedFile();
        fileInfo.setRelatedTo(relatedTo);
        fileInfo.setFileName(fileName);
        fileInfo.setTopic(topic);
        fileInfo.setFullName(new File(path, fileName).getAbsolutePath());
        return fileInfo;
    }

    /**
     * set fileRootPath
     * @param pFileRootPath fileRootPath
     */
    public void setFileRootPath(String pFileRootPath) {
        fileRootPath = pFileRootPath;

    }

    /**
     * set uploadedFileService
     * @param pUploadedFileService uploadedFileService
     */
    public void setUploadedFileService(UploadedFileService pUploadedFileService) {
        uploadedFileService = pUploadedFileService;
    }

}
